package org.zjvis.graph.analysis.service.http;

import com.alibaba.fastjson.JSONObject;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import org.zjvis.graph.analysis.service.exception.BaseErrorCode;
import org.zjvis.graph.analysis.service.exception.GraphAnalysisException;

import javax.annotation.PostConstruct;
import javax.net.ssl.SSLContext;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Component
public class RestTemplateUtil {

    private final static Logger logger = LoggerFactory.getLogger("RestTemplateUtil");

    @Value("${restful.dataScienceServer.address}")
    private String dataScienceServer;

    private RestTemplate restTemplate;

    @Autowired
    private HttpServletRequest request;


    @PostConstruct
    public void init() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
        SSLContext sslContext = org.apache.http.ssl.SSLContexts.custom()
                .loadTrustMaterial(null, new TrustSelfSignedStrategy())
                .build();

        SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext,
                NoopHostnameVerifier.INSTANCE);

        CloseableHttpClient httpClient = HttpClients.custom()
                .setSSLSocketFactory(csf)
                .build();

        HttpComponentsClientHttpRequestFactory requestFactory =
                new HttpComponentsClientHttpRequestFactory();

        requestFactory.setHttpClient(httpClient);
        this.restTemplate = new RestTemplate(requestFactory);
    }

    public <T> JSONObject post(String serviceRoute, T body) {
        String url = dataScienceServer + serviceRoute;
        Cookie[] cks = request.getCookies();
        if (cks == null || cks.length == 0) {
            throw new GraphAnalysisException(BaseErrorCode.COOKIE_INVALID);
        }
        List<String> cookies = Arrays.stream(cks).map(c-> c.getName() + "=" + c.getValue()).collect(Collectors.toList());
        HttpHeaders headers = new HttpHeaders();
        headers.put(HttpHeaders.COOKIE, cookies);
        HttpEntity<T> req = new HttpEntity<>(body, headers);
        ResponseEntity<JSONObject> exchange = restTemplate
                .exchange(url, HttpMethod.POST,
                        req, JSONObject.class);
        JSONObject resp = exchange.getBody();
        if (resp == null || !resp.getBoolean("success")) {
            throw new GraphAnalysisException(BaseErrorCode.HTTP_ERROR, resp != null ? resp.getString("message") : null, null);
        }
        return resp;
    }

    public <T> JSONObject postWithNoCookie(String serviceRoute, T body) {
        String url = dataScienceServer + serviceRoute;
        HttpEntity<T> req = new HttpEntity<>(body);
        ResponseEntity<JSONObject> exchange = restTemplate
                .exchange(url, HttpMethod.POST,
                        req, JSONObject.class);
        JSONObject resp = exchange.getBody();
        logger.info("postWithNoCookie: " + resp);
        if (resp == null || !resp.getBoolean("success")) {
            throw new GraphAnalysisException(BaseErrorCode.HTTP_ERROR, resp != null ? resp.getString("message") : null, null);
        }
        return resp;
    }




}
